﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.ComponentModel;
using System.Reflection;
using System.Xml.Linq;

namespace devtm.Editor.TypeSelector.AttributeBuilder
{


    public class Parameter : TreeViewItem, INotifyPropertyChanged
    {

        public Parameter(AttributeBuilder.Constructor constructor)
        {
            this.constructor = constructor;
            bool b = constructor.Items.Count == 0;
            // constructor.Items.Count == 1 || 
            TitleChoosePropertyLastUserControl h1 = new TitleChoosePropertyLastUserControl();
            h1.IsFirst = b;
            
            h1.AvailbleProperty = new Func<List<PropertyInfo>>(() => constructor.GetAvailbleProperty());
            h1.AddProperty = new Action<PropertyInfo>(e => constructor.AddProperty(e));
            h1.Lost = new Action<object>(e => constructor.RefreshLost(e));
            this.Header = h1;

            if (!b)
                RefreshAdd();

        }

        public Parameter(AttributeBuilder.Constructor constructor, PropertyInfo property)
        {
            this.constructor = constructor;
            this.Property = property;

            bool b = constructor.Items.Count == 1 || constructor.Items.Count == 0;

            this.Name = property.Name;
            this.Type = property.PropertyType;

            TitleChoosePropertyTypeUserControl h = new TitleChoosePropertyTypeUserControl();
            h.IsFirst = b;
            h.DataContext = constructor.AttributeMap.Parent.Root.RootListe;
            h.NameProperty.Content = property.Name;

            h.Lost = new Action<object>(e => constructor.RefreshLost(e));
            h.Parametre = this;
            this.Header = h;

        }

        public Parameter(AttributeBuilder.Constructor constructor, ParameterInfo parameter)
        {
           
            bool b = constructor.Items.Count == 1 || constructor.Items.Count == 0;

            this.constructor = constructor;
            this.parameter = parameter;

            this.Name = parameter.Name;
            this.Type = parameter.ParameterType;

            TitleChoosePropertyTypeUserControl h = new TitleChoosePropertyTypeUserControl();
            h.IsFirst = b;
            h.DataContext = constructor.AttributeMap.Parent.Root.RootListe;
            h.NameProperty.Content = parameter.Name;
            h.Lost = new Action<object>(e => constructor.RefreshLost(e));
            h.Parametre = this;
            this.Header = h;

        }

        public Type Type { get; set; }

        #region INotifyPropertyChanged

        protected void MyPropertyChanged(PropertyChangedEventArgs e)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, e);
        }

        protected void MyPropertyChanged(string propertyName)
        {
            MyPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private AttributeBuilder.Constructor constructor;
        private System.Reflection.ParameterInfo parameter;

        #endregion

        public PropertyInfo Property { get; set; }

        internal void RefreshAdd()
        {
            (this.Header as TitleChoosePropertyLastUserControl).RefreshAdd();
        }

        internal void Lost(object e)
        {

            if (e == Header)
                return;

            TitleChoosePropertyTypeUserControl b = (Header as TitleChoosePropertyTypeUserControl);

            if (b != null)
                b.VisibilityEditor(System.Windows.Visibility.Collapsed);

        }


        private Object _value = string.Empty;
        public string ValueString 
        {
            get { return _value.ToString(); }
            set
            {

                _value = CastValue(Type, value);

                TitleChoosePropertyTypeUserControl h = Header as TitleChoosePropertyTypeUserControl;
                h.MyPropertyChanged("SelectedItem");
                h.MyPropertyChanged("SelectedItemString");
            }
        }

        public static object CastValue(Type type,string value)
        {

            if (type == typeof(string))
                return value;

            MethodInfo[] p = type.GetMethods();

            foreach (MethodInfo item in p)

                if (item.Name == "Parse" && item.GetParameters().Count() == 1 && item.GetParameters().First().ParameterType == typeof(string))
                {
                    if (string.IsNullOrEmpty(value))
                        value = InitializeDefaultValue(type);

                    try
                    {
                        return item.Invoke(null, new object[] { value });
                    }
                    catch (Exception)
                    {
                        throw;
                    }
                }
                

           if (type == typeof(Type))
                return Type.GetType(value);
            
            else
                return value;
            
            #region hide

            //if (type == typeof(DateTime))
            //{
            //    if (!string.IsNullOrEmpty(value))
            //        return DateTime.Parse(value);
            //    else 
            //        return new DateTime();
            //}

            //else if (type == typeof(TimeSpan))
            //{
            //    if (!string.IsNullOrEmpty(value))
            //        return TimeSpan.Parse(value);
            //    else 
            //        return new TimeSpan();

            //}

            //else if (type == typeof(byte))
            //{
            //    if (!string.IsNullOrEmpty(value))
            //        return byte.Parse(value);
            //    else 
            //        return (byte)0;

            //}

            //else if (type == typeof(long))
            //{
            //    if (!string.IsNullOrEmpty(value))
            //        return long.Parse(value);
            //    else 
            //        return 0L;

            //}

            //else if (type == typeof(decimal))
            //{
            //    if (!string.IsNullOrEmpty(value))
            //        return decimal.Parse(value);
            //    else
            //        return 0m;

            //}

            //else if (type == typeof(float))
            //{
            //    if (!string.IsNullOrEmpty(value))
            //        return float.Parse(value);
            //    else
            //        return 0;
            //}

            //else if (type == typeof(Single))
            //{
            //    if (!string.IsNullOrEmpty(value))
            //        return Single.Parse(value);
            //    else
            //        return 0f;

            //}

            //else if (type == typeof(int))
            //{
            //    if (!string.IsNullOrEmpty(value)) 
            //        return int.Parse(value);
            //    else 
            //        return 0;

            //}

            //else if (type == typeof(short))
            //{
            //    if (!string.IsNullOrEmpty(value)) 
            //        return short.Parse(value);
            //    else 
            //        return (short)0;

            //}

            #endregion        

        }

        private static string InitializeDefaultValue(Type type)
        {

            if (type.IsPrimitive)
                return "0";
            
            else if (type == typeof(DateTime))
                    return new DateTime().ToString();

            else if (type == typeof(TimeSpan))
                    return new TimeSpan().ToString();
            
            return string.Empty;

        }

        public Object Value
        {
            get { return _value; }
            set 
            {
                _value = value;
                TitleChoosePropertyTypeUserControl h = Header as TitleChoosePropertyTypeUserControl;
                h.MyPropertyChanged("SelectedItem");
                h.MyPropertyChanged("SelectedItemString");
            }
        }

        internal XElement Serialize()
        {

            if (Header is TitleChoosePropertyLastUserControl)
                return null;

            string h = this.Type == typeof(Type) ? (Value as Type).AssemblyQualifiedName : ValueString;

            return new XElement(Name
                , new XAttribute("type", parameter != null ? "parameter" : "property")
                , new XCData(h));

        }

        internal void UnSerialize(XElement node)
        {
            ValueString = node.Value;
        }

    }

}


